﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace IntelliTraceLauncher
{
    public static class ThreadHelper
    {
        delegate void UpdateCallback(Form wf, Control ctrl);

        delegate void SetTopMostCallback(Form wf);

        delegate void SetTextCallback(Form wf, Control ctrl, string text);
        delegate void SetTextToolStripMenuItemCallback(Form wf, ContextMenuStrip strip, ToolStripMenuItem ctrl, string text);
        delegate void SetTextToolStripStatusLabelCallback(Form wf, StatusStrip strip, ToolStripStatusLabel ctrl, string text);

        delegate void AddTextCallback(Form wf, Control ctrl, string text);

        delegate void SetVisibleCallback(Form wf, Control ctrl, bool visible);
        delegate void SetVisibleToolStripMenuItemCallback(Form wf, ContextMenuStrip strip, ToolStripMenuItem ctrl, bool visible);
        delegate void SetVisibleToolStripStatusLabelCallback(Form wf, StatusStrip strip, ToolStripStatusLabel ctrl, bool visible);

        delegate void SetOpacityCallback(Form wf, double opacity);
        delegate void SetLocationCallback(Form wf, Control ctrl, System.Drawing.Point location);
        delegate void SetSizeCallback(Form wf, Control ctrl, System.Drawing.Size size);

        #region Update the UI of various controls.

        /// <summary>
        /// Update the UI of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's UI should be updated.</param>
        public static void Update(Form winForm, Control ctrl)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                UpdateCallback callbackDelegate = new UpdateCallback(Update);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl });
            }
            else
            {
                ctrl.Update();
            }
        }

        #endregion Update the UI of various controls.

        #region Set the form as TopMost.

        /// <summary>
        /// Set the form as TopMost.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        public static void SetTopMost(Form winForm)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (winForm.InvokeRequired)
            {
                SetTopMostCallback callbackDelegate = new SetTopMostCallback(SetTopMost);
                winForm.Invoke(callbackDelegate, new object[] { winForm });
            }
            else
            {
                winForm.TopMost = true;
                winForm.BringToFront();
            }
        }

        #endregion Set the form as TopMost.

        #region Set text property of various controls.

        /// <summary>
        /// Set text property of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's text property should be set.</param>
        /// <param name="text">Text value to be placed into control.</param>
        public static void SetText(Form winForm, Control ctrl, string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                SetTextCallback callbackDelegate = new SetTextCallback(SetText);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl, text });
            }
            else
            {
                ctrl.Text = text;
            }
        }

        /// <summary>
        /// Set text property of various ToolStripMenuItem objects.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="strip">ContextMenuStrip that holds the ToolStripMenuItem object.</param>
        /// <param name="ctrl">Control who's text property should be set.</param>
        /// <param name="text">Text value to be placed into control.</param>
        public static void SetText(Form winForm, ContextMenuStrip strip, ToolStripMenuItem ctrl, string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (strip.InvokeRequired)
            {
                SetTextToolStripMenuItemCallback callbackDelegate = new SetTextToolStripMenuItemCallback(SetText);
                winForm.Invoke(callbackDelegate, new object[] { winForm, strip, ctrl, text });
            }
            else
            {
                ctrl.Text = text;
            }
        }

        /// <summary>
        /// Set text property of various ToolStripStatusLabel objects.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="strip">StatusStrip that holds the ToolStripStatusLabel object.</param>
        /// <param name="ctrl">Control who's text property should be set.</param>
        /// <param name="text">Text value to be placed into control.</param>
        public static void SetText(Form winForm, StatusStrip strip, ToolStripStatusLabel ctrl, string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (strip.InvokeRequired)
            {
                SetTextToolStripStatusLabelCallback callbackDelegate = new SetTextToolStripStatusLabelCallback(SetText);
                winForm.Invoke(callbackDelegate, new object[] { winForm, strip, ctrl, text });
            }
            else
            {
                ctrl.Text = text;
            }
        }

        #endregion Set text property of various controls.

        #region Append text property of various controls.

        /// <summary>
        /// Set text property of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's text property should be set.</param>
        /// <param name="text">Text value to be appended into control.</param>
        public static void AddText(Form winForm, Control ctrl, string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                AddTextCallback callbackDelegate = new AddTextCallback(AddText);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl, text });
            }
            else
            {
                ctrl.Text += text;
            }
        }

        #endregion Append text property of various controls.

        #region Set visible property of various controls.

        /// <summary>
        /// Set visible property of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's visible property should be set.</param>
        /// <param name="visible">Visible value to be set in control.</param>
        public static void SetVisible(Form winForm, Control ctrl, bool visible)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                SetVisibleCallback callbackDelegate = new SetVisibleCallback(SetVisible);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl, visible });
            }
            else
            {
                ctrl.Visible = visible;
            }
        }

        /// <summary>
        /// Set visible property of various ToolStripMenuItem objects.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="strip">ContextMenuStrip that holds the ToolStripMenuItem object.</param>
        /// <param name="ctrl">Control who's visible property should be set.</param>
        /// <param name="visible">Visible value to be set in control.</param>
        public static void SetVisible(Form winForm, ContextMenuStrip strip, ToolStripMenuItem ctrl, bool visible)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true. 
            if (strip.InvokeRequired)
            {
                SetVisibleToolStripMenuItemCallback callbackDelegate = new SetVisibleToolStripMenuItemCallback(SetVisible);
                winForm.Invoke(callbackDelegate, new object[] { winForm, strip, ctrl, visible });
            }
            else
            {
                ctrl.Visible = visible;
            }
        }

        /// <summary>
        /// Set visible property of various ToolStripStatusLabel objects.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="strip">StatusStrip that holds the ToolStripStatusLabel object.</param>
        /// <param name="ctrl">Control who's visible property should be set.</param>
        /// <param name="visible">Visible value to be set in control.</param>
        public static void SetVisible(Form winForm, StatusStrip strip, ToolStripStatusLabel ctrl, bool visible)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true. 
            if (strip.InvokeRequired)
            {
                SetVisibleToolStripStatusLabelCallback callbackDelegate = new SetVisibleToolStripStatusLabelCallback(SetVisible);
                winForm.Invoke(callbackDelegate, new object[] { winForm, strip, ctrl, visible });
            }
            else
            {
                ctrl.Visible = visible;
            }
        }

        #endregion Set visible property of various controls.

        #region Set the opacity property of a forms.

        /// <summary>
        /// Set the opacity property of a forms.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="opacity">Opacity value to be placed into form.</param>
        public static void SetOpacity(Form winForm, double opacity)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (winForm.InvokeRequired)
            {
                SetOpacityCallback callbackDelegate = new SetOpacityCallback(SetOpacity);
                winForm.Invoke(callbackDelegate, new object[] { winForm, opacity });
            }
            else
            {
                winForm.Opacity = opacity;
            }
        }

        #endregion Set the opacity property of a forms.

        #region Set location property of various controls.

        /// <summary>
        /// Set location property of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's location property should be set.</param>
        /// <param name="location">Location value to be set in control.</param>
        public static void SetLocation(Form winForm, Control ctrl, System.Drawing.Point location)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                SetLocationCallback callbackDelegate = new SetLocationCallback(SetLocation);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl, location });
            }
            else
            {
                ctrl.Location = location;
            }
        }

        #endregion Set location property of various controls.

        #region Set size property of various controls.

        /// <summary>
        /// Set size property of various controls.
        /// </summary>
        /// <param name="winForm">The calling form.</param>
        /// <param name="ctrl">Control who's location property should be set.</param>
        /// <param name="location">Location value to be set in control.</param>
        public static void SetSize(Form winForm, Control ctrl, System.Drawing.Size size)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (ctrl.InvokeRequired)
            {
                SetSizeCallback callbackDelegate = new SetSizeCallback(SetSize);
                winForm.Invoke(callbackDelegate, new object[] { winForm, ctrl, size });
            }
            else
            {
                ctrl.Size = size;
            }
        }

        #endregion Set size property of various controls.
    }
}
